-- Haskore Live!
--
-- David Siegel <djsiegel@seas.upenn.edu>
-- Jonathan Coveney <jcoveney@wharton.upenn.edu>
--
-- HaskoreUtil.hs
--

-- | Module 'HaskoreUtil' provides a somewhat saner interface to the parts of
-- Haskore that Haskore Live uses most. These parts include facilities for
-- converting between Music, Performance, and Midi types.
module HaskoreUtil ( allInstruments
                   , mergePerformances
                   , musicDuration
                   , musicToMidi
                   , musicToPerformance
                   , performanceDuration
                   , performanceToMidi
                   , runTests
                   ) where

import Test.HUnit

import Basics
import GeneralMidi (genMidiMap)
import HaskToMidi (performToMidi)
import OutputMidi (outputMidiFile)
import Performance (Performance, Event, eTime, eDur, perform, merge)
import TestHaskore (mToMF, defPMap, defCon, defUpm, gmUpm)

-- | Returns an array of all instrument names supported in Haskore Live.
allInstruments :: [IName]
allInstruments = map fst genMidiMap

-- | Writes a Music datatype to a midi file at the given path.
musicToMidi :: FilePath -> Music -> IO ()
musicToMidi = mToMF defPMap defCon gmUpm

-- | Converts a Music datatype to a Performance.
musicToPerformance :: Music -> Performance
musicToPerformance = perform defPMap defCon

-- | Returns the duration of a well-formed Performance. We're fairly certain
-- that this does not report the correct duration.
musicDuration :: Music -> Float
musicDuration =  performanceDuration . musicToPerformance

-- | Returns the duration of a well-formed Performance.
performanceDuration :: Performance -> Float
performanceDuration [] = 0
performanceDuration p  = eTime (last p) + eDur (last p)

-- | Similar to musicToMidi: given a Performance datatype, writes a midi file
-- containing that Performance to the specified path.
performanceToMidi :: FilePath -> Performance -> IO ()
performanceToMidi fp p = outputMidiFile fp (performToMidi p gmUpm)

-- | Given a list of Performances, this collates the Performances into a single
-- Performance equivalent to all Performances performed in parallel.
mergePerformances :: [Performance] -> Performance
mergePerformances [] = []
mergePerformances ps = foldr1 merge ps

-- | Runs unit tests.
--
-- At the moment, we define no tests for this module, as all functions are
-- merely aliases to Haskore functions, which should be tested separately.
runTests = runTestTT $
    TestList []
            
